/**
 * 文件处理工具类 - JavaScript版本
 * 提供文件类型检测、大小校验、格式转换、预览等功能
 * 可直接复制粘贴使用，无需任何依赖
 */

/**
 * 文件类型枚举
 */
const FILE_TYPES = {
  IMAGE: 'image',
  VIDEO: 'video',
  AUDIO: 'audio',
  DOCUMENT: 'document',
  ARCHIVE: 'archive',
  CODE: 'code',
  UNKNOWN: 'unknown'
};

/**
 * 文件信息构造函数
 * @param {string} name - 文件名
 * @param {number} size - 文件大小
 * @param {string} type - 文件类型
 * @param {number} lastModified - 最后修改时间
 * @param {string} fileType - 文件类型分类
 * @param {string} extension - 文件扩展名
 * @param {string} mimeType - MIME类型
 * @param {boolean} isImage - 是否为图片
 * @param {boolean} isVideo - 是否为视频
 * @param {boolean} isAudio - 是否为音频
 * @param {boolean} isDocument - 是否为文档
 * @param {boolean} isArchive - 是否为压缩包
 * @param {boolean} isCode - 是否为代码文件
 */
function FileInfo(name, size, type, lastModified, fileType, extension, mimeType, isImage, isVideo, isAudio, isDocument, isArchive, isCode) {
  this.name = name;
  this.size = size;
  this.type = type;
  this.lastModified = lastModified;
  this.fileType = fileType;
  this.extension = extension;
  this.mimeType = mimeType;
  this.isImage = isImage;
  this.isVideo = isVideo;
  this.isAudio = isAudio;
  this.isDocument = isDocument;
  this.isArchive = isArchive;
  this.isCode = isCode;
}

/**
 * 文件校验结果构造函数
 * @param {boolean} isValid - 是否有效
 * @param {string} message - 消息
 * @param {Array<string>} errors - 错误列表
 * @param {Array<string>} warnings - 警告列表
 */
function FileValidationResult(isValid, message, errors, warnings) {
  this.isValid = isValid;
  this.message = message;
  this.errors = errors;
  this.warnings = warnings;
}

/**
 * 批量文件校验结果构造函数
 * @param {boolean} isValid - 是否有效
 * @param {string} message - 消息
 * @param {Array<FileInfo>} validFiles - 有效文件列表
 * @param {Array<Object>} invalidFiles - 无效文件列表
 * @param {number} totalCount - 总数量
 * @param {number} validCount - 有效数量
 * @param {number} invalidCount - 无效数量
 * @param {number} totalSize - 总大小
 * @param {number} validSize - 有效大小
 * @param {number} invalidSize - 无效大小
 */
function BatchFileValidationResult(isValid, message, validFiles, invalidFiles, totalCount, validCount, invalidCount, totalSize, validSize, invalidSize) {
  this.isValid = isValid;
  this.message = message;
  this.validFiles = validFiles;
  this.invalidFiles = invalidFiles;
  this.totalCount = totalCount;
  this.validCount = validCount;
  this.invalidCount = invalidCount;
  this.totalSize = totalSize;
  this.validSize = validSize;
  this.invalidSize = invalidSize;
}

/**
 * 文件类型规则配置
 */
const FILE_TYPE_RULES = {
  // 图片类型
  IMAGE_JPEG: {
    extensions: ['jpg', 'jpeg'],
    mimeTypes: ['image/jpeg'],
    description: 'JPEG图片'
  },
  IMAGE_PNG: {
    extensions: ['png'],
    mimeTypes: ['image/png'],
    description: 'PNG图片'
  },
  IMAGE_GIF: {
    extensions: ['gif'],
    mimeTypes: ['image/gif'],
    description: 'GIF图片'
  },
  IMAGE_WEBP: {
    extensions: ['webp'],
    mimeTypes: ['image/webp'],
    description: 'WebP图片'
  },
  IMAGE_SVG: {
    extensions: ['svg'],
    mimeTypes: ['image/svg+xml'],
    description: 'SVG图片'
  },
  IMAGE_BMP: {
    extensions: ['bmp'],
    mimeTypes: ['image/bmp'],
    description: 'BMP图片'
  },
  IMAGE_ICO: {
    extensions: ['ico'],
    mimeTypes: ['image/x-icon', 'image/vnd.microsoft.icon'],
    description: 'ICO图标'
  },

  // 视频类型
  VIDEO_MP4: {
    extensions: ['mp4'],
    mimeTypes: ['video/mp4'],
    description: 'MP4视频'
  },
  VIDEO_AVI: {
    extensions: ['avi'],
    mimeTypes: ['video/x-msvideo'],
    description: 'AVI视频'
  },
  VIDEO_MOV: {
    extensions: ['mov'],
    mimeTypes: ['video/quicktime'],
    description: 'MOV视频'
  },
  VIDEO_WMV: {
    extensions: ['wmv'],
    mimeTypes: ['video/x-ms-wmv'],
    description: 'WMV视频'
  },
  VIDEO_WEBM: {
    extensions: ['webm'],
    mimeTypes: ['video/webm'],
    description: 'WebM视频'
  },

  // 音频类型
  AUDIO_MP3: {
    extensions: ['mp3'],
    mimeTypes: ['audio/mpeg'],
    description: 'MP3音频'
  },
  AUDIO_WAV: {
    extensions: ['wav'],
    mimeTypes: ['audio/wav'],
    description: 'WAV音频'
  },
  AUDIO_OGG: {
    extensions: ['ogg'],
    mimeTypes: ['audio/ogg'],
    description: 'OGG音频'
  },
  AUDIO_AAC: {
    extensions: ['aac'],
    mimeTypes: ['audio/aac'],
    description: 'AAC音频'
  },

  // 文档类型
  DOCUMENT_PDF: {
    extensions: ['pdf'],
    mimeTypes: ['application/pdf'],
    description: 'PDF文档'
  },
  DOCUMENT_DOC: {
    extensions: ['doc'],
    mimeTypes: ['application/msword'],
    description: 'Word文档'
  },
  DOCUMENT_DOCX: {
    extensions: ['docx'],
    mimeTypes: ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
    description: 'Word文档'
  },
  DOCUMENT_XLS: {
    extensions: ['xls'],
    mimeTypes: ['application/vnd.ms-excel'],
    description: 'Excel文档'
  },
  DOCUMENT_XLSX: {
    extensions: ['xlsx'],
    mimeTypes: ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
    description: 'Excel文档'
  },
  DOCUMENT_PPT: {
    extensions: ['ppt'],
    mimeTypes: ['application/vnd.ms-powerpoint'],
    description: 'PowerPoint文档'
  },
  DOCUMENT_PPTX: {
    extensions: ['pptx'],
    mimeTypes: ['application/vnd.openxmlformats-officedocument.presentationml.presentation'],
    description: 'PowerPoint文档'
  },
  DOCUMENT_TXT: {
    extensions: ['txt'],
    mimeTypes: ['text/plain'],
    description: '文本文件'
  },
  DOCUMENT_RTF: {
    extensions: ['rtf'],
    mimeTypes: ['application/rtf'],
    description: 'RTF文档'
  },

  // 压缩文件类型
  ARCHIVE_ZIP: {
    extensions: ['zip'],
    mimeTypes: ['application/zip'],
    description: 'ZIP压缩包'
  },
  ARCHIVE_RAR: {
    extensions: ['rar'],
    mimeTypes: ['application/x-rar-compressed'],
    description: 'RAR压缩包'
  },
  ARCHIVE_7Z: {
    extensions: ['7z'],
    mimeTypes: ['application/x-7z-compressed'],
    description: '7Z压缩包'
  },
  ARCHIVE_TAR: {
    extensions: ['tar'],
    mimeTypes: ['application/x-tar'],
    description: 'TAR压缩包'
  },

  // 代码文件类型
  CODE_JS: {
    extensions: ['js'],
    mimeTypes: ['application/javascript', 'text/javascript'],
    description: 'JavaScript文件'
  },
  CODE_TS: {
    extensions: ['ts'],
    mimeTypes: ['application/typescript', 'text/typescript'],
    description: 'TypeScript文件'
  },
  CODE_CSS: {
    extensions: ['css'],
    mimeTypes: ['text/css'],
    description: 'CSS文件'
  },
  CODE_HTML: {
    extensions: ['html', 'htm'],
    mimeTypes: ['text/html'],
    description: 'HTML文件'
  },
  CODE_JSON: {
    extensions: ['json'],
    mimeTypes: ['application/json'],
    description: 'JSON文件'
  },
  CODE_XML: {
    extensions: ['xml'],
    mimeTypes: ['application/xml', 'text/xml'],
    description: 'XML文件'
  }
};

/**
 * 获取文件扩展名
 * @param {string} filename - 文件名
 * @returns {string} 扩展名（小写）
 */
function getFileExtension(filename) {
  if (!filename || typeof filename !== 'string') {
    return '';
  }
  
  const lastDotIndex = filename.lastIndexOf('.');
  if (lastDotIndex === -1 || lastDotIndex === filename.length - 1) {
    return '';
  }
  
  return filename.substring(lastDotIndex + 1).toLowerCase();
}

/**
 * 获取文件MIME类型
 * @param {File} file - 文件对象
 * @returns {string} MIME类型
 */
function getFileMimeType(file) {
  return file.type || '';
}

/**
 * 检测文件类型
 * @param {File} file - 文件对象
 * @returns {string} 文件类型
 */
function detectFileType(file) {
  const extension = getFileExtension(file.name);
  const mimeType = getFileMimeType(file).toLowerCase();
  
  // 图片类型检测
  if (mimeType.startsWith('image/') || 
      ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'ico'].includes(extension)) {
    return FILE_TYPES.IMAGE;
  }
  
  // 视频类型检测
  if (mimeType.startsWith('video/') || 
      ['mp4', 'avi', 'mov', 'wmv', 'webm', 'flv', 'mkv'].includes(extension)) {
    return FILE_TYPES.VIDEO;
  }
  
  // 音频类型检测
  if (mimeType.startsWith('audio/') || 
      ['mp3', 'wav', 'ogg', 'aac', 'flac', 'm4a'].includes(extension)) {
    return FILE_TYPES.AUDIO;
  }
  
  // 文档类型检测
  if (mimeType.includes('pdf') || mimeType.includes('document') || mimeType.includes('text') ||
      ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'rtf'].includes(extension)) {
    return FILE_TYPES.DOCUMENT;
  }
  
  // 压缩文件类型检测
  if (mimeType.includes('zip') || mimeType.includes('rar') || mimeType.includes('7z') ||
      ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'].includes(extension)) {
    return FILE_TYPES.ARCHIVE;
  }
  
  // 代码文件类型检测
  if (mimeType.includes('javascript') || mimeType.includes('typescript') || mimeType.includes('css') ||
      ['js', 'ts', 'css', 'html', 'htm', 'json', 'xml', 'py', 'java', 'cpp', 'c'].includes(extension)) {
    return FILE_TYPES.CODE;
  }
  
  return FILE_TYPES.UNKNOWN;
}

/**
 * 获取文件信息
 * @param {File} file - 文件对象
 * @returns {FileInfo} 文件信息
 */
function getFileInfo(file) {
  const extension = getFileExtension(file.name);
  const mimeType = getFileMimeType(file);
  const fileType = detectFileType(file);
  
  return new FileInfo(
    file.name,
    file.size,
    mimeType,
    file.lastModified,
    fileType,
    extension,
    mimeType,
    fileType === FILE_TYPES.IMAGE,
    fileType === FILE_TYPES.VIDEO,
    fileType === FILE_TYPES.AUDIO,
    fileType === FILE_TYPES.DOCUMENT,
    fileType === FILE_TYPES.ARCHIVE,
    fileType === FILE_TYPES.CODE
  );
}

/**
 * 校验单个文件
 * @param {File} file - 文件对象
 * @param {Object} [sizeConfig] - 大小配置
 * @param {Object} [typeConfig] - 类型配置
 * @returns {FileValidationResult} 校验结果
 */
function validateFile(file, sizeConfig, typeConfig) {
  const errors = [];
  const warnings = [];
  
  // 基础文件检查
  if (!file) {
    return new FileValidationResult(false, '文件不存在', ['文件不存在'], []);
  }
  
  const fileInfo = getFileInfo(file);
  
  // 大小检查
  if (sizeConfig) {
    if (sizeConfig.maxSize && file.size > sizeConfig.maxSize) {
      errors.push(`文件大小超过限制，最大允许 ${formatFileSize(sizeConfig.maxSize)}`);
    }
    
    if (sizeConfig.minSize && file.size < sizeConfig.minSize) {
      errors.push(`文件大小不足，最小需要 ${formatFileSize(sizeConfig.minSize)}`);
    }
  }
  
  // 类型检查
  if (typeConfig) {
    // 允许的类型检查
    if (typeConfig.allowedTypes && typeConfig.allowedTypes.length > 0) {
      const isAllowedType = typeConfig.allowedTypes.some(type => 
        fileInfo.mimeType.includes(type) || fileInfo.fileType === type
      );
      if (!isAllowedType) {
        errors.push(`文件类型不在允许列表中`);
      }
    }
    
    // 允许的扩展名检查
    if (typeConfig.allowedExtensions && typeConfig.allowedExtensions.length > 0) {
      if (!typeConfig.allowedExtensions.includes(fileInfo.extension)) {
        errors.push(`文件扩展名不在允许列表中`);
      }
    }
    
    // 禁止的类型检查
    if (typeConfig.blockedTypes && typeConfig.blockedTypes.length > 0) {
      const isBlockedType = typeConfig.blockedTypes.some(type => 
        fileInfo.mimeType.includes(type) || fileInfo.fileType === type
      );
      if (isBlockedType) {
        errors.push(`文件类型在禁止列表中`);
      }
    }
    
    // 禁止的扩展名检查
    if (typeConfig.blockedExtensions && typeConfig.blockedExtensions.length > 0) {
      if (typeConfig.blockedExtensions.includes(fileInfo.extension)) {
        errors.push(`文件扩展名在禁止列表中`);
      }
    }
  }
  
  // 文件名检查
  if (!file.name || file.name.trim().length === 0) {
    errors.push('文件名不能为空');
  }
  
  // 文件大小警告
  if (file.size > 50 * 1024 * 1024) { // 50MB
    warnings.push('文件较大，可能影响上传速度');
  }
  
  return new FileValidationResult(
    errors.length === 0,
    errors.length === 0 ? '文件校验通过' : '文件校验失败',
    errors,
    warnings
  );
}

/**
 * 批量文件校验
 * @param {Array<File>} files - 文件数组
 * @param {Object} [sizeConfig] - 大小配置
 * @param {Object} [typeConfig] - 类型配置
 * @returns {BatchFileValidationResult} 批量校验结果
 */
function validateBatchFiles(files, sizeConfig, typeConfig) {
  const validFiles = [];
  const invalidFiles = [];
  let totalSize = 0;
  let validSize = 0;
  let invalidSize = 0;
  
  for (const file of files) {
    const fileInfo = getFileInfo(file);
    totalSize += file.size;
    
    const validation = validateFile(file, sizeConfig, typeConfig);
    
    if (validation.isValid) {
      validFiles.push(fileInfo);
      validSize += file.size;
    } else {
      invalidFiles.push({
        file: fileInfo,
        reason: validation.errors.join(', ')
      });
      invalidSize += file.size;
    }
  }
  
  // 总大小检查
  if (sizeConfig?.maxTotalSize && totalSize > sizeConfig.maxTotalSize) {
    return new BatchFileValidationResult(
      false,
      `总文件大小超过限制，最大允许 ${formatFileSize(sizeConfig.maxTotalSize)}`,
      [],
      files.map(file => ({
        file: getFileInfo(file),
        reason: '总文件大小超过限制'
      })),
      files.length,
      0,
      files.length,
      totalSize,
      0,
      totalSize
    );
  }
  
  // 文件数量检查
  if (sizeConfig?.maxFileCount && files.length > sizeConfig.maxFileCount) {
    return new BatchFileValidationResult(
      false,
      `文件数量超过限制，最大允许 ${sizeConfig.maxFileCount} 个`,
      [],
      files.map(file => ({
        file: getFileInfo(file),
        reason: '文件数量超过限制'
      })),
      files.length,
      0,
      files.length,
      totalSize,
      0,
      totalSize
    );
  }
  
  return new BatchFileValidationResult(
    invalidFiles.length === 0,
    invalidFiles.length === 0 ? '所有文件校验通过' : `发现 ${invalidFiles.length} 个无效文件`,
    validFiles,
    invalidFiles,
    files.length,
    validFiles.length,
    invalidFiles.length,
    totalSize,
    validSize,
    invalidSize
  );
}

/**
 * 格式化文件大小
 * @param {number} bytes - 字节数
 * @param {number} [decimals=2] - 小数位数
 * @returns {string} 格式化后的文件大小
 */
function formatFileSize(bytes, decimals = 2) {
  if (bytes === 0) return '0 Bytes';
  
  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
  
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  
  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

/**
 * 检查文件是否为图片
 * @param {File} file - 文件对象
 * @returns {boolean} 是否为图片
 */
function isImageFile(file) {
  return detectFileType(file) === FILE_TYPES.IMAGE;
}

/**
 * 检查文件是否为视频
 * @param {File} file - 文件对象
 * @returns {boolean} 是否为视频
 */
function isVideoFile(file) {
  return detectFileType(file) === FILE_TYPES.VIDEO;
}

/**
 * 检查文件是否为音频
 * @param {File} file - 文件对象
 * @returns {boolean} 是否为音频
 */
function isAudioFile(file) {
  return detectFileType(file) === FILE_TYPES.AUDIO;
}

/**
 * 检查文件是否为文档
 * @param {File} file - 文件对象
 * @returns {boolean} 是否为文档
 */
function isDocumentFile(file) {
  return detectFileType(file) === FILE_TYPES.DOCUMENT;
}

/**
 * 检查文件是否为压缩包
 * @param {File} file - 文件对象
 * @returns {boolean} 是否为压缩包
 */
function isArchiveFile(file) {
  return detectFileType(file) === FILE_TYPES.ARCHIVE;
}

/**
 * 检查文件是否为代码文件
 * @param {File} file - 文件对象
 * @returns {boolean} 是否为代码文件
 */
function isCodeFile(file) {
  return detectFileType(file) === FILE_TYPES.CODE;
}

/**
 * 生成文件预览URL
 * @param {File} file - 文件对象
 * @returns {string} 预览URL
 */
function createFilePreviewUrl(file) {
  return URL.createObjectURL(file);
}

/**
 * 释放文件预览URL
 * @param {string} url - 预览URL
 */
function revokeFilePreviewUrl(url) {
  URL.revokeObjectURL(url);
}

/**
 * 读取文件内容为文本
 * @param {File} file - 文件对象
 * @returns {Promise<string>} 文件内容
 */
function readFileAsText(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = () => reject(reader.error);
    reader.readAsText(file);
  });
}

/**
 * 读取文件内容为DataURL
 * @param {File} file - 文件对象
 * @returns {Promise<string>} DataURL
 */
function readFileAsDataURL(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = () => reject(reader.error);
    reader.readAsDataURL(file);
  });
}

/**
 * 读取文件内容为ArrayBuffer
 * @param {File} file - 文件对象
 * @returns {Promise<ArrayBuffer>} ArrayBuffer
 */
function readFileAsArrayBuffer(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = () => reject(reader.error);
    reader.readAsArrayBuffer(file);
  });
}

/**
 * 获取图片尺寸
 * @param {File} file - 图片文件
 * @returns {Promise<Object>} 图片尺寸
 */
function getImageDimensions(file) {
  return new Promise((resolve, reject) => {
    if (!isImageFile(file)) {
      reject(new Error('文件不是图片类型'));
      return;
    }
    
    const img = new Image();
    img.onload = () => {
      resolve({ width: img.width, height: img.height });
    };
    img.onerror = () => {
      reject(new Error('无法加载图片'));
    };
    img.src = createFilePreviewUrl(file);
  });
}

/**
 * 压缩图片
 * @param {File} file - 图片文件
 * @param {number} [quality=0.8] - 压缩质量 (0-1)
 * @param {number} [maxWidth=1920] - 最大宽度
 * @param {number} [maxHeight=1080] - 最大高度
 * @returns {Promise<Blob>} 压缩后的图片
 */
function compressImage(file, quality = 0.8, maxWidth = 1920, maxHeight = 1080) {
  return new Promise((resolve, reject) => {
    if (!isImageFile(file)) {
      reject(new Error('文件不是图片类型'));
      return;
    }
    
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const img = new Image();
    
    img.onload = () => {
      // 计算压缩后的尺寸
      let { width, height } = img;
      
      if (width > maxWidth || height > maxHeight) {
        const ratio = Math.min(maxWidth / width, maxHeight / height);
        width *= ratio;
        height *= ratio;
      }
      
      canvas.width = width;
      canvas.height = height;
      
      // 绘制压缩后的图片
      ctx?.drawImage(img, 0, 0, width, height);
      
      canvas.toBlob(
        (blob) => {
          if (blob) {
            resolve(blob);
          } else {
            reject(new Error('图片压缩失败'));
          }
        },
        file.type,
        quality
      );
    };
    
    img.onerror = () => {
      reject(new Error('无法加载图片'));
    };
    
    img.src = createFilePreviewUrl(file);
  });
}

/**
 * 文件工具类
 */
class FileUtils {
  /**
   * 获取支持的文件类型列表
   * @returns {Array<string>} 支持的文件类型
   */
  static getSupportedFileTypes() {
    return Object.keys(FILE_TYPE_RULES);
  }
  
  /**
   * 根据扩展名获取文件类型规则
   * @param {string} extension - 扩展名
   * @returns {Object|null} 文件类型规则
   */
  static getFileTypeRuleByExtension(extension) {
    for (const [key, rule] of Object.entries(FILE_TYPE_RULES)) {
      if (rule.extensions.includes(extension.toLowerCase())) {
        return { key, ...rule };
      }
    }
    return null;
  }
  
  /**
   * 根据MIME类型获取文件类型规则
   * @param {string} mimeType - MIME类型
   * @returns {Object|null} 文件类型规则
   */
  static getFileTypeRuleByMimeType(mimeType) {
    for (const [key, rule] of Object.entries(FILE_TYPE_RULES)) {
      if (rule.mimeTypes.includes(mimeType.toLowerCase())) {
        return { key, ...rule };
      }
    }
    return null;
  }
  
  /**
   * 生成文件下载链接
   * @param {File} file - 文件对象
   * @param {string} [filename] - 下载文件名
   * @returns {string} 下载链接
   */
  static createDownloadLink(file, filename) {
    const url = createFilePreviewUrl(file);
    const link = document.createElement('a');
    link.href = url;
    link.download = filename || file.name;
    return url;
  }
  
  /**
   * 触发文件下载
   * @param {File} file - 文件对象
   * @param {string} [filename] - 下载文件名
   */
  static downloadFile(file, filename) {
    const url = createFilePreviewUrl(file);
    const link = document.createElement('a');
    link.href = url;
    link.download = filename || file.name;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    revokeFilePreviewUrl(url);
  }
}

// 创建全局实例
const fileUtils = new FileUtils();

// 导出所有功能（支持多种使用方式）
if (typeof module !== 'undefined' && module.exports) {
  // Node.js环境
  module.exports = {
    FileUtils,
    fileUtils,
    FileInfo,
    FileValidationResult,
    BatchFileValidationResult,
    FILE_TYPES,
    FILE_TYPE_RULES,
    getFileExtension,
    getFileMimeType,
    detectFileType,
    getFileInfo,
    validateFile,
    validateBatchFiles,
    formatFileSize,
    isImageFile,
    isVideoFile,
    isAudioFile,
    isDocumentFile,
    isArchiveFile,
    isCodeFile,
    createFilePreviewUrl,
    revokeFilePreviewUrl,
    readFileAsText,
    readFileAsDataURL,
    readFileAsArrayBuffer,
    getImageDimensions,
    compressImage
  };
} else if (typeof window !== 'undefined') {
  // 浏览器环境
  window.FileUtils = FileUtils;
  window.fileUtils = fileUtils;
  window.FileInfo = FileInfo;
  window.FileValidationResult = FileValidationResult;
  window.BatchFileValidationResult = BatchFileValidationResult;
  window.FILE_TYPES = FILE_TYPES;
  window.FILE_TYPE_RULES = FILE_TYPE_RULES;
  window.getFileExtension = getFileExtension;
  window.getFileMimeType = getFileMimeType;
  window.detectFileType = detectFileType;
  window.getFileInfo = getFileInfo;
  window.validateFile = validateFile;
  window.validateBatchFiles = validateBatchFiles;
  window.formatFileSize = formatFileSize;
  window.isImageFile = isImageFile;
  window.isVideoFile = isVideoFile;
  window.isAudioFile = isAudioFile;
  window.isDocumentFile = isDocumentFile;
  window.isArchiveFile = isArchiveFile;
  window.isCodeFile = isCodeFile;
  window.createFilePreviewUrl = createFilePreviewUrl;
  window.revokeFilePreviewUrl = revokeFilePreviewUrl;
  window.readFileAsText = readFileAsText;
  window.readFileAsDataURL = readFileAsDataURL;
  window.readFileAsArrayBuffer = readFileAsArrayBuffer;
  window.getImageDimensions = getImageDimensions;
  window.compressImage = compressImage;
}
